# 基于X6.js封装流程图

# 需求分析

  1. 支持自定义节点、边(支持通过前端框架进行自定义)

  2. 支持配置边的折线

  3. 支持布局算法

  4. 支持通过滚动条拖动画布

  5. 事件系统

  6. 缩放、导出等

  7. 支持Echarts渲染图表

# 插件选型

# G6.js

官方文档 (opens new window)

# 优点

丰富的插件系统及自定义效果,支持自动布局。

# 缺点

该插件定位更趋向于数据的展示,在流程图这个方向上不够专业。

且不支持通过前端框架自定义节点,只支持通过G2.js渲染图表。

# logicFlow

官方文档 (opens new window)

相比之下该插件功能就比较单薄。

不支持自动布局

不支持框架渲染

自带插件少

# x6.js

官方文档 (opens new window)

# 优点

专门做流程图的,有很多专业的功能。

丰富的插件系统

支持通过前端框架进行渲染

支持使用Echarts渲染图表

性能测试1000+节点无卡顿

# 缺点

无内置布局算法,需手动实现。

最终决定使用X6.js来实现流程图。

# 项目架构

# 目录

└───demo // 示例
└───docs // 文档
└───src
│   └───event // 事件
│   └───hooks // 钩子函数
│   └───layout // 布局
│   └───method // 方法函数
│   └───shape // 自定义元素
│   const.ts // 常量
│   types.ts // 类型定义
│   useFlow.ts // 使用入口

# event

由于x6.js已做好完善的事件系统,使用者通过:

graph.on('event', () => {});
graph.emit('event', () => {});

即可控制事件。

此处只针对edge的hover效果进行了处理。

# hooks

初始化流程图的主要地方:

配置初始化、

数据初始化、

布局、

混入方法、

模拟数据、

使用插件

等等功能。

# layout

由于x6.js无内置布局算法,所以这里自己封装了一套。

目前默认使用dagre算法进行布局,用户可配置其属性,已有布局位置时可手动关闭自动布局。

# method

graph方法的补充

挂在其实例上,可直接调用。

# shape

已内置了部分节点、边、label

支持使用者在外部自定义。

# mock

为了测试性能,支持了模拟数据功能 。

可手动配置数量及层级去模拟出想要的数据。

# 技术难点

# 布局算法

如果有多个分支且数量不对等时,dagre算法会靠下对齐,不符合设计。

这里通过查找出分支中x最小的坐标,进行手动对齐。

# 交叉连线

单个节点存在多连线、跨级连线的场景时,默认的线的路由的走向不理想。

这里手动计算出线的转折点,进行渲染。

# label位置

x6.js对label的位置只支持配置百分比及绝对位置,无法根据节点类型进行区分。

这里通过分析节点类型,自动更换边类型,达到控制label位置的需求。

# label渲染

官方文档只给出了react.js的案例,分析案例,发现原理是通过svg先渲染出容器,然后通过react去挂载自定义内容到该容器中。

这种效果通过vue也能实现。

在默认配置中增加onEdgeLabelRendered方法,在渲染出容器后,通过vuehrender函数实现将vue组件挂载到容器上。

# 点击事件透传

由于X6node_modules\@antv\x6\src\graph\view.ts中直接监听了各种事件,导致在vue自定义节点中,会同时触发收起和点击两个事件。

通过查阅源码,发现有暴露guard函数来控制事件冒泡。

通过在初始化Graph时传入guard函数,迭代判断父节点的类名是否包含指定的需要停止冒泡的类名,从而解决同时触发点击事件的效果。